package com.jichangxiu.common.entity.bo;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.jichangxiu.common.constant.Constants;
import com.jichangxiu.common.utils.StrUtils;
import lombok.Getter;
import org.springframework.http.MediaType;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;

@Getter
public class RequestWrapper extends HttpServletRequestWrapper implements Serializable {

    private static final long serialVersionUID = 1L;

    private byte[] body;

    public RequestWrapper(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, String body) throws UnsupportedEncodingException {
        super(httpServletRequest);
        httpServletRequest.setCharacterEncoding(Constants.UTF_8);
        httpServletResponse.setCharacterEncoding(Constants.UTF_8);
        this.body = body.getBytes(StandardCharsets.UTF_8);
    }

    public RequestWrapper(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
        super(httpServletRequest);
        httpServletRequest.setCharacterEncoding(Constants.UTF_8);
        httpServletResponse.setCharacterEncoding(Constants.UTF_8);
        this.body = IoUtil.readUtf8(super.getInputStream()).getBytes(StandardCharsets.UTF_8);
    }

    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        return filterXss(value);
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> map = new LinkedHashMap<>();
        Map<String, String[]> parameters = super.getParameterMap();
        for (String key : parameters.keySet()) {
            String[] values = parameters.get(key);
            for (int i = 0; i < values.length; i++)
                values[i] = filterXss(values[i]);
            map.put(key, values);
        }
        return map;
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] parameters = super.getParameterValues(name);
        if (parameters == null || parameters.length == 0)
            return null;
        for (int i = 0; i < parameters.length; i++)
            parameters[i] = filterXss(parameters[i]);
        return parameters;
    }

    @Override
    public String getParameter(String name) {
        return filterXss(super.getParameter(name));
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        // 返回新的 ServletInputStream
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);

        // 如果是 json 数据，则不处理
        if (!StrUtil.startWithIgnoreCase(this.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
            return new ServletInputStream() {
                @Override
                public int read() throws IOException {
                    return byteArrayInputStream.read();
                }

                @Override
                public int available() throws IOException {
                    return body.length;
                }

                @Override
                public boolean isFinished() {
                    return true;
                }

                @Override
                public boolean isReady() {
                    return true;
                }

                @Override
                public void setReadListener(ReadListener readListener) {

                }
            };
        }

        // 读取内容，进行xss过滤
        String content = filterXss(IoUtil.readUtf8(byteArrayInputStream));

        // 返回新的 ServletInputStream
        final ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(content.getBytes());

        return new ServletInputStream() {
            @Override
            public int read() {
                return arrayInputStream.read();
            }

            @Override
            public int available() throws IOException {
                return body.length;
            }

            @Override
            public boolean isFinished() {
                return true;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    private String filterXss(String content) {
        if (StrUtil.isBlank(content))
            return content;
        return StrUtils.xssFilter(content);
    }

}
